﻿// Decompiled with JetBrains decompiler
// Type: DnProcessSimulateCommands.SweptVolume.CApSVInterferenceZoneSamplingManager
// Assembly: DnProcessSimulateCommands, Version=2402.0.0.890, Culture=neutral, PublicKeyToken=null
// MVID: A885D881-AEDF-447E-852A-6F13102E089C
// Assembly location: C:\Program Files\Tecnomatix_2402\eMPower\DotNetCommands\DnProcessSimulateCommands.dll

using EngineeringInternalExtension;
using System;
using System.Collections;
using System.Collections.ObjectModel;
using System.Windows.Forms;
using Tecnomatix.Engineering;


namespace DnProcessSimulateCommands.SweptVolume;

public class CApSVInterferenceZoneSamplingManager : CApSamplingManager
{
  private TxColor NO_COLLISION_COLOR = TxColor.TxColorBlue;
  private TxColor COLLISION_COLOR = TxColor.TxColorRed;
  private TxColor NEAR_MISS_COLOR = TxColor.TxColorYellow;
  private ArrayList m_interferenceZones;
  private ITxLocatableObject m_checkWithObject;
  private CApSVInterferenceZoneData m_interferenceZoneData;
  private CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState m_state;
  private TxCollisionQueryParams m_queryParams;
  private TxCollisionPair m_collisionPair;
  private TxObjectList m_activePairs;
  private bool m_isNearMissCollision;
  private TxDisplayableObjectVisibility m_checkWithObjectOriginalVisibillity;
  private bool m_shouldCreateTCPTrack;
  private DnProcessSimulateCommands.TCPFTracker.TCPFTracker m_tcpfTracker;
  private TxObjectList m_createdTCPFTrackComponents;
  private double m_distanceAtLastLocationReached;
  private ITxLocatableObject m_nearestObjectAtLastLocationReached;
  private EApInterferenceZoneErrorType m_errorDetected;
  private bool m_supportInsideZones;

  public CApSVInterferenceZoneSamplingManager(
    CApSVTimeSampleSimulationHandler simHandler,
    CApSVSamplingObjectsHandler objHandler,
    ITxLocatableObject checkWithObject,
    bool includeCables)
    : base((CApSimulationHandler) simHandler, objHandler, includeCables)
  {
    this.m_checkWithObject = checkWithObject;
    this.m_interferenceZones = new ArrayList();
    this.m_interferenceZoneData = (CApSVInterferenceZoneData) null;
    this.m_state = CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.NO_INTERFERENCE_ZONE;
    this.m_errorDetected = EApInterferenceZoneErrorType.NO_ERROR;
    this.m_shouldCreateTCPTrack = false;
    this.m_tcpfTracker = (DnProcessSimulateCommands.TCPFTracker.TCPFTracker) null;
    this.m_createdTCPFTrackComponents = new TxObjectList();
    this.m_supportInsideZones = false;
    this.m_activePairs = new TxObjectList();
    this.deactivateAndStoreAllActiveCollisionPairs();
    TxCollisionPairCreationData pairCreationData = new TxCollisionPairCreationData("Interference Zone");
    TxObjectList txObjectList = new TxObjectList(1);
    ((Collection<ITxObject>) txObjectList).Add((ITxObject) this.m_checkWithObject);
    pairCreationData.FirstList = txObjectList;
    this.m_collisionPair = TxApplication.ActiveDocument.CollisionRoot.CreateCollisionPair(pairCreationData);
    this.m_collisionPair.Active = true;
    this.m_queryParams = new TxCollisionQueryParams();
    this.m_queryParams.Mode = (TxCollisionQueryParams.TxCollisionQueryMode) 0;
    this.m_queryParams.UseNearMiss = true;
    this.m_queryParams.NearMissDistance = 0.0;
  }

  public double Clearance
  {
    get => this.m_queryParams.NearMissDistance;
    set => this.m_queryParams.NearMissDistance = value;
  }

  public CApSVInterferenceZoneData[] InterferenceZones
  {
    get
    {
      CApSVInterferenceZoneData[] interferenceZones = new CApSVInterferenceZoneData[this.m_interferenceZones.Count];
      for (int index = 0; index < interferenceZones.Length; ++index)
        interferenceZones[index] = this.m_interferenceZones[index] as CApSVInterferenceZoneData;
      return interferenceZones;
    }
  }

  public bool TCPTrack
  {
    get => this.m_shouldCreateTCPTrack;
    set => this.m_shouldCreateTCPTrack = value;
  }

  public TxObjectList CreatedTCPFTrackComponents => this.m_createdTCPFTrackComponents;

  public EApInterferenceZoneErrorType Error => this.m_errorDetected;

  public bool SupportInsideZones
  {
    set => this.m_supportInsideZones = value;
  }

  protected override void sample()
  {
    if (this.m_objHandler.hasObjectsListChanged())
      this.updateCollisionPair();
    bool colliding = this.doesCollisionOccur();
    if (this.m_tcpfTracker != null)
      this.updateTCPFTracker(colliding);
    this.dispatchSamplingByState(colliding);
    if (this.m_simHandler.RefreshDisplay)
      return;
    Application.DoEvents();
  }

  protected override void internalInitializeSampling()
  {
    this.TSSimHandler().locationReached += new CApSVOrderedLocationsSimulationHandler.locationReachedEventHandler(this.onLocationReached);
    ITxDisplayableObject checkWithObject = this.m_checkWithObject as ITxDisplayableObject;
    this.m_checkWithObjectOriginalVisibillity = checkWithObject.Visibility;
    checkWithObject.Display();
    if (!this.shouldCreateTCPTrack())
      return;
    ITxLocatableObject rootObject = this.m_objHandler.RootObject as ITxLocatableObject;
    if (!(rootObject is ITxRobot))
      return;
    ITxRobot itxRobot = rootObject as ITxRobot;
    this.m_tcpfTracker = new DnProcessSimulateCommands.TCPFTracker.TCPFTracker(rootObject, itxRobot.TCPF);
    this.m_tcpfTracker.StartRecording();
    this.m_tcpfTracker.Color = this.NO_COLLISION_COLOR;
    this.m_tcpfTracker.PauseRecording();
  }

  protected override void internalFinalizeSampling()
  {
    this.deleteCollisionPair();
    this.activateStoredCollisionPairs();
    ITxDisplayableObject checkWithObject = this.m_checkWithObject as ITxDisplayableObject;
    if (this.m_checkWithObjectOriginalVisibillity == 2)
      checkWithObject.Blank();
    if (this.m_tcpfTracker != null)
    {
      this.m_tcpfTracker.StopRecording();
      foreach (ITxObject createdComponent in (Collection<ITxObject>) this.m_tcpfTracker.CreatedComponents)
      {
        if (!((Collection<ITxObject>) this.m_createdTCPFTrackComponents).Contains(createdComponent))
          ((Collection<ITxObject>) this.m_createdTCPFTrackComponents).Add(createdComponent);
      }
    }
    if (this.m_errorDetected == EApInterferenceZoneErrorType.NO_ERROR && this.m_interferenceZones.Count == 0)
      this.m_errorDetected = EApInterferenceZoneErrorType.IZ_NO_INTERFERENCE_ZONES_FOUND;
    this.TSSimHandler().locationReached -= new CApSVOrderedLocationsSimulationHandler.locationReachedEventHandler(this.onLocationReached);
  }

  private void updateCollisionPair()
  {
    this.m_collisionPair.SecondList = this.m_objHandler.getObjectsForSampling();
  }

  private void deactivateAndStoreAllActiveCollisionPairs()
  {
    TxCollisionRoot collisionRoot = TxApplication.ActiveDocument.CollisionRoot;
    ((Collection<ITxObject>) this.m_activePairs).Clear();
    foreach (TxCollisionPair pair in (Collection<ITxObject>) collisionRoot.PairList)
    {
      if (TxCollisionPair.op_Inequality(pair, (ITxObject) null) && pair.Active)
      {
        ((Collection<ITxObject>) this.m_activePairs).Add((ITxObject) pair);
        pair.Active = false;
      }
    }
  }

  private void activateStoredCollisionPairs()
  {
    foreach (TxCollisionPair activePair in (Collection<ITxObject>) this.m_activePairs)
    {
      if (TxCollisionPair.op_Inequality(activePair, (ITxObject) null))
        activePair.Active = true;
    }
    ((Collection<ITxObject>) this.m_activePairs).Clear();
  }

  private void deleteCollisionPair()
  {
    if (!TxCollisionPair.op_Inequality(this.m_collisionPair, (ITxObject) null))
      return;
    this.m_collisionPair.Delete();
    this.m_collisionPair = (TxCollisionPair) null;
  }

  private bool doesCollisionOccur()
  {
    bool flag = false;
    foreach (ITxObject second in (Collection<ITxObject>) this.m_collisionPair.SecondList)
    {
      if (second is ITxCable)
        TxFlxCableEx.UpdateControlPoints(second as ITxCable);
    }
    TxCollisionQueryResults collidingObjects = TxApplication.ActiveDocument.CollisionRoot.GetCollidingObjects(this.m_queryParams);
    if (collidingObjects.States.Count > 0)
    {
      flag = true;
      this.determineCollisionType(collidingObjects);
    }
    return flag;
  }

  private TxCollisionState.TxCollisionStateType determineCollisionType(
    TxCollisionQueryResults results)
  {
    TxCollisionState.TxCollisionStateType collisionType = (TxCollisionState.TxCollisionStateType) 2;
    foreach (TxCollisionState state in results.States)
    {
      if (state.Type == 5)
        collisionType = (TxCollisionState.TxCollisionStateType) 5;
    }
    this.m_isNearMissCollision = collisionType == 2;
    return collisionType;
  }

  private CApSVTimeSampleSimulationHandler TSSimHandler()
  {
    return this.m_simHandler as CApSVTimeSampleSimulationHandler;
  }

  private bool shouldCreateTCPTrack()
  {
    bool tcpTrack = false;
    if (this.m_shouldCreateTCPTrack)
      tcpTrack = !(this.m_simHandler.SimulatingObject is TxObjectFlowOperation);
    return tcpTrack;
  }

  private void updateTCPFTracker(bool colliding)
  {
    if (this.m_tcpfTracker.Paused)
      this.m_tcpfTracker.PauseRecording();
    TxColor txColor = this.NO_COLLISION_COLOR;
    if (colliding)
      txColor = !this.m_isNearMissCollision ? this.COLLISION_COLOR : this.NEAR_MISS_COLOR;
    if (!TxColor.op_Inequality(txColor, this.m_tcpfTracker.Color))
      return;
    this.m_tcpfTracker.Color = txColor;
  }

  private void findNearestObjectAndDistance(
    out ITxLocatableObject locNearestObj,
    out double distance)
  {
    TxObjectList objectsForSampling = this.m_objHandler.getObjectsForSampling();
    double num1 = double.MaxValue;
    ITxLocatableObject itxLocatableObject1 = (ITxLocatableObject) null;
    double num2 = 0.01;
    foreach (ITxObject itxObject in (Collection<ITxObject>) objectsForSampling)
    {
      try
      {
        TxObjectList txObjectList = new TxObjectList();
        ((Collection<ITxObject>) txObjectList).Add(itxObject);
        if (!new TxBoundingBoxCalculator(txObjectList).CalculateVisibleObjectsBoundingBox().IsEmpty)
        {
          ITxLocatableObject itxLocatableObject2 = (ITxLocatableObject) null;
          double maxValue = double.MaxValue;
          TxVector txVector1;
          TxVector txVector2;
          if (itxObject is ITxLocatableObject)
          {
            ITxLocatableObject itxLocatableObject3 = itxObject as ITxLocatableObject;
            itxLocatableObject3.GetMinimalDistance(this.m_checkWithObject, ref maxValue, ref txVector1, ref txVector2);
            itxLocatableObject2 = itxLocatableObject3;
          }
          else if (itxObject is ITxCable)
          {
            ITxCable itxCable = itxObject as ITxCable;
            TxFlxCableEx.UpdateControlPoints(itxCable);
            itxCable.GetMinimalDistance(this.m_checkWithObject, ref maxValue, ref txVector1, ref txVector2);
            itxLocatableObject2 = (ITxLocatableObject) TxFlxCableEx.LinkedRobot(itxCable);
          }
          if (maxValue < num1)
          {
            num1 = maxValue;
            itxLocatableObject1 = itxLocatableObject2;
          }
        }
      }
      catch (Exception ex)
      {
      }
      if (num1 < num2)
        break;
    }
    distance = num1;
    locNearestObj = itxLocatableObject1;
  }

  private void onLocationReached(object sender, EventArgs args)
  {
    if (this.confirmFirstAndLastLocationAreCollisionFree() || this.m_supportInsideZones)
    {
      try
      {
        ITxLocatableObject locNearestObj;
        double distance;
        this.findNearestObjectAndDistance(out locNearestObj, out distance);
        this.m_nearestObjectAtLastLocationReached = locNearestObj;
        this.m_distanceAtLastLocationReached = distance;
      }
      catch (TxCanNotCheckMeasurementOfInvisibleObjectException ex)
      {
        this.m_errorDetected = EApInterferenceZoneErrorType.IZ_CHECK_WITH_OBJECT_BLANK_ERROR;
        this.stopSampling();
      }
      catch (Exception ex)
      {
        this.m_errorDetected = EApInterferenceZoneErrorType.IZ_OPERATION_FAILED;
        this.stopSampling();
      }
    }
    else
      this.stopSampling();
  }

  private bool confirmFirstAndLastLocationAreCollisionFree()
  {
    bool flag = true;
    CApSVTimeSampleSimulationHandler simulationHandler = this.TSSimHandler();
    ITxLocationOperation lastLocationReached = simulationHandler.LastLocationReached;
    ITxLocationOperation firstLocation = simulationHandler.FirstLocation;
    ITxLocationOperation lastLocation = simulationHandler.LastLocation;
    if (lastLocationReached == firstLocation || lastLocationReached == lastLocation)
    {
      this.updateCollisionPair();
      if (this.doesCollisionOccur())
      {
        this.m_errorDetected = EApInterferenceZoneErrorType.IZ_FIRST_OR_LAST_LOCATION_IN_ZONE_ERROR;
        flag = false;
      }
    }
    return flag;
  }

  private void dispatchSamplingByState(bool colliding)
  {
    switch (this.m_state)
    {
      case CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.NO_INTERFERENCE_ZONE:
        this.sampleAtNoInterferenceZoneState(colliding);
        break;
      case CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.INTERFERENCE_ZONE_STARTED:
        this.sampleAtInterferenceZoneStartedState(colliding);
        break;
      case CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.LOCATION_IN_INTERFERENCE_ZONE_DETECTED:
        this.sampleAtLocationInInterferenceZoneDetectedState(colliding);
        break;
      case CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.INTERFERENCE_ZONE_EXITED:
        this.sampleAtInterferenceZoneExitedState(colliding);
        break;
      default:
        throw new Exception("CApSVInterferenceZoneSamplingManager: Unknown state");
    }
  }

  private void sampleAtNoInterferenceZoneState(bool colliding)
  {
    if (!colliding)
      return;
    CApSVTimeSampleSimulationHandler simulationHandler = this.TSSimHandler();
    this.m_interferenceZoneData = new CApSVInterferenceZoneData();
    this.m_interferenceZoneData.Operation = simulationHandler.SimulatingObject;
    this.m_interferenceZoneData.SimulatedObject = this.m_objHandler.RootObject as ITxLocatableObject;
    this.m_interferenceZoneData.CheckWithObject = this.m_checkWithObject;
    ITxLocationOperation lastLocationReached = simulationHandler.LastLocationReached;
    if (this.m_supportInsideZones && lastLocationReached == simulationHandler.FirstLocation && this.m_errorDetected == EApInterferenceZoneErrorType.IZ_FIRST_OR_LAST_LOCATION_IN_ZONE_ERROR)
    {
      this.m_interferenceZoneData.Enter.InsideInterference = true;
    }
    else
    {
      this.m_interferenceZoneData.Enter.LocationOutside = lastLocationReached;
      this.m_interferenceZoneData.Enter.TimeAtOutsideLocation = simulationHandler.TimeAtLastLocationReached;
    }
    this.m_interferenceZoneData.Enter.TimeAtZone = simulationHandler.CurrentTime;
    this.m_interferenceZoneData.Enter.NearestObject = this.m_nearestObjectAtLastLocationReached;
    this.m_interferenceZoneData.Enter.Distance = this.m_distanceAtLastLocationReached;
    this.m_state = CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.INTERFERENCE_ZONE_STARTED;
  }

  private void sampleAtInterferenceZoneStartedState(bool colliding)
  {
    if (colliding)
    {
      ITxLocationOperation lastLocationReached = this.TSSimHandler().LastLocationReached;
      if (lastLocationReached == this.m_interferenceZoneData.Enter.LocationOutside)
        return;
      this.m_interferenceZoneData.Enter.LocationInside = lastLocationReached;
      this.m_interferenceZoneData.Exit.LocationInside = lastLocationReached;
      this.m_state = CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.LOCATION_IN_INTERFERENCE_ZONE_DETECTED;
      if (!this.m_supportInsideZones || lastLocationReached != this.TSSimHandler().LastLocation)
        return;
      this.m_interferenceZoneData.Exit.InsideInterference = true;
      this.m_interferenceZones.Add((object) this.m_interferenceZoneData);
    }
    else
    {
      if (this.m_supportInsideZones && this.m_interferenceZoneData.Enter.LocationOutside == null && this.m_interferenceZoneData.Enter.LocationInside == null && this.m_errorDetected == EApInterferenceZoneErrorType.IZ_FIRST_OR_LAST_LOCATION_IN_ZONE_ERROR)
      {
        ITxLocationOperation firstLocation = this.TSSimHandler().FirstLocation;
        this.m_interferenceZoneData.Enter.LocationInside = firstLocation;
        this.m_interferenceZoneData.Exit.LocationInside = firstLocation;
      }
      this.m_interferenceZoneData.Exit.TimeAtZone = this.m_simHandler.CurrentTime;
      this.m_state = CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.INTERFERENCE_ZONE_EXITED;
    }
  }

  private void sampleAtLocationInInterferenceZoneDetectedState(bool colliding)
  {
    if (colliding)
    {
      ITxLocationOperation lastLocationReached = this.TSSimHandler().LastLocationReached;
      if (lastLocationReached == this.m_interferenceZoneData.Exit.LocationInside)
        return;
      this.m_interferenceZoneData.Exit.LocationInside = lastLocationReached;
      if (!this.m_supportInsideZones || lastLocationReached != this.TSSimHandler().LastLocation)
        return;
      this.m_interferenceZoneData.Exit.InsideInterference = true;
      this.m_interferenceZones.Add((object) this.m_interferenceZoneData);
    }
    else
    {
      this.m_interferenceZoneData.Exit.TimeAtZone = this.m_simHandler.CurrentTime;
      this.m_state = CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.INTERFERENCE_ZONE_EXITED;
    }
  }

  private void sampleAtInterferenceZoneExitedState(bool colliding)
  {
    if (colliding)
    {
      this.m_state = this.m_interferenceZoneData.Enter.LocationInside == null ? CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.INTERFERENCE_ZONE_STARTED : CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.LOCATION_IN_INTERFERENCE_ZONE_DETECTED;
      this.dispatchSamplingByState(colliding);
    }
    else
    {
      CApSVTimeSampleSimulationHandler simulationHandler = this.TSSimHandler();
      ITxLocationOperation lastLocationReached = simulationHandler.LastLocationReached;
      ITxLocationOperation locationOperation = this.m_interferenceZoneData.Exit.LocationInside == null ? (this.m_interferenceZoneData.Enter.LocationInside == null ? this.m_interferenceZoneData.Enter.LocationOutside : this.m_interferenceZoneData.Enter.LocationInside) : this.m_interferenceZoneData.Exit.LocationInside;
      if (lastLocationReached == locationOperation)
        return;
      this.m_interferenceZoneData.Exit.LocationOutside = lastLocationReached;
      this.m_interferenceZoneData.Exit.TimeAtOutsideLocation = simulationHandler.TimeAtLastLocationReached;
      this.m_interferenceZoneData.Exit.NearestObject = this.m_nearestObjectAtLastLocationReached;
      this.m_interferenceZoneData.Exit.Distance = this.m_distanceAtLastLocationReached;
      this.m_interferenceZones.Add((object) this.m_interferenceZoneData);
      this.m_state = CApSVInterferenceZoneSamplingManager.EApSVInterferenceZoneDetectionState.NO_INTERFERENCE_ZONE;
    }
  }

  private enum EApSVInterferenceZoneDetectionState
  {
    NO_INTERFERENCE_ZONE,
    INTERFERENCE_ZONE_STARTED,
    LOCATION_IN_INTERFERENCE_ZONE_DETECTED,
    INTERFERENCE_ZONE_EXITED,
  }
}
